summaryrefslogtreecommitdiff
path: root/app/api/data-room/[projectId]/upload/route.ts
blob: 60bbc10f1b9de79dbb1bc251f9f5172c7730cd9e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// app/api/data-room/[projectId]/upload/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { getServerSession } from 'next-auth/next';
import { authOptions } from '@/app/api/auth/[...nextauth]/route';
import { FileService, type FileAccessContext } from '@/lib/services/fileService';
import { saveDRMFile, saveFileStream } from '@/lib/file-stroage';

export async function POST(
  request: NextRequest,
  { params }: { params: { projectId: string } }
) {
  try {
    const session = await getServerSession(authOptions);
    if (!session?.user) {
      return NextResponse.json({ error: '인증이 필요합니다' }, { status: 401 });
    }

    const context: FileAccessContext = {
      userId: Number(session.user.id),
      userDomain: session.user.domain || 'partners',
      userEmail: session.user.email,
      ipAddress: request.ip || request.headers.get('x-forwarded-for') || undefined,
      userAgent: request.headers.get('user-agent') || undefined,
    };

    // 내부 사용자만 업로드 가능
    if (session.user.domain === 'partners') {
      return NextResponse.json(
        { error: '파일 업로드 권한이 없습니다' },
        { status: 403 }
      );
    }

    const formData = await request.formData();
    const file = formData.get('file') as File;
    const category = formData.get('category') as string;
    const parentId = formData.get('parentId') as string | null;
    const fileSize = formData.get('fileSize') as string | null;

    if (!file) {
      return NextResponse.json(
        { error: '파일이 제공되지 않았습니다' },
        { status: 400 }
      );
    }

    // 대용량 파일 임계값 (10MB)
    const LARGE_FILE_THRESHOLD = 10 * 1024 * 1024;
    const actualFileSize = fileSize ? parseInt(fileSize) : file.size;

    let result;
    
    // 파일 크기에 따라 다른 저장 방법 사용
    if (actualFileSize > LARGE_FILE_THRESHOLD) {
      console.log(`🚀 대용량 파일 스트리밍 저장: ${file.name} (${(actualFileSize / 1024 / 1024).toFixed(2)}MB)`);
      
      // 대용량 파일은 스트리밍 저장 사용
      result = await saveFileStream({
        file,
        directory: `projects/${params.projectId}`,
        originalName: file.name,
        userId: session.user.id
      });
    } else {
      console.log(`📦 일반 파일 저장: ${file.name} (${(actualFileSize / 1024 / 1024).toFixed(2)}MB)`);
      
      // 작은 파일은 기존 DRM 저장 방식 사용
      result = await saveDRMFile(
        file,
        async (file) => file.arrayBuffer(), // 이미 복호화된 데이터
        `projects/${params.projectId}`,
        session.user.id
      );
    }

    if (!result.success) {
      return NextResponse.json(
        { error: result.error || '파일 저장에 실패했습니다' },
        { status: 500 }
      );
    }

    // DB에 파일 정보 저장
    const fileService = new FileService();
    const newFile = await fileService.createFileItem(
      {
        name: result.originalName || file.name,
        type: 'file',
        category: category as 'public' | 'restricted' | 'confidential' | 'internal',
        parentId,
        size: result.fileSize || actualFileSize,
        mimeType: file.type,
        filePath: result.publicPath,
        projectId: params.projectId,
      },
      context
    );

    return NextResponse.json({
      ...newFile,
      uploadResult: {
        ...result,
        uploadMethod: actualFileSize > LARGE_FILE_THRESHOLD ? 'stream' : 'buffer',
        fileSizeMB: (actualFileSize / 1024 / 1024).toFixed(2)
      },
    }, { status: 201 });

  } catch (error) {
    console.error('파일 업로드 오류:', error);
    return NextResponse.json(
      { 
        error: '파일 업로드에 실패했습니다',
        details: error instanceof Error ? error.message : undefined 
      },
      { status: 500 }
    );
  }
}

// 업로드 진행률 확인 (선택적)
export async function GET(
  request: NextRequest,
  { params }: { params: { projectId: string } }
) {
  try {
    const session = await getServerSession(authOptions);
    if (!session?.user) {
      return NextResponse.json({ error: '인증이 필요합니다' }, { status: 401 });
    }

    // 업로드 상태 확인 로직 (필요시 구현)
    return NextResponse.json({ message: '업로드 상태 확인 엔드포인트' });
  } catch (error) {
    return NextResponse.json(
      { error: '상태 확인 실패' },
      { status: 500 }
    );
  }
}